package com.boot2.core.dao;

import com.boot2.core.exception.BusinessException;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import java.util.Arrays;
import java.util.List;

/**
 * 新增分页的多项属性
 *
 * @author zhangweilin
 * @version V1.0
 * @date 2016年4月19日 下午5:46:46
 * @description
 */
@ApiModel("分页后的结果集，一般只为mybatis分页后的结果")
public class PageInfo<T> {
    // 当前页
    @ApiModelProperty("当前页,默认为第一页")
    private int pageNo = 1;
    // 每页的数量
    @ApiModelProperty("每页的数量,默认每页20条")
    private int pageSize = 20;
    // 当前页的数量
    @ApiModelProperty("当前页的数量")
    private int currentPageSize;
    // 由于startRow和endRow不常用，这里说个具体的用法
    // 可以在页面中"显示startRow到endRow 共size条数据"

    // 当前页面第一个元素在数据库中的行号
    @ApiModelProperty("当前页面第一个元素在数据库中的行号")
    private int startRow;
    // 当前页面最后一个元素在数据库中的行号
    @ApiModelProperty("当前页面最后一个元素在数据库中的行号")
    private int endRow;
    // 总记录数
    @ApiModelProperty("总记录数")
    private long totalNum;
    // 总页数
    @ApiModelProperty("总页数")
    private int pageNum;
    // 结果集
//    @JsonIgnore
    @ApiModelProperty("结果集")
    private List<T> list;

    // 第一页
    @ApiModelProperty("第一页")
    private int firstPage;
    // 前一页
    @ApiModelProperty("前一页")
    private int prePage;
    // 下一页
    @ApiModelProperty("下一页")
    private int nextPage;
    // 最后一页
    @ApiModelProperty("最后一页")
    private int lastPage;

    // 是否为第一页
    @ApiModelProperty("是否为第一页")
    private boolean isFirstPage = false;
    // 是否为最后一页
    @ApiModelProperty("是否为最后一页")
    private boolean isLastPage = false;
    // 是否有前一页
    @ApiModelProperty("是否有前一页")
    private boolean hasPreviousPage = false;
    // 是否有下一页
    @ApiModelProperty("是否有下一页")
    private boolean hasNextPage = false;
    // 导航页码数
    @ApiModelProperty("导航页码数")
    private int navigatePages;
    // 所有导航页号
    @ApiModelProperty("所有导航页号")
    private int[] navigatepageNums;

    public PageInfo() {
    }

    /**
     * 包装Page对象
     *
     * @param resultList
     */
    public PageInfo(List<T> resultList) {
        this(resultList, 8);
    }

    /**
     * 包装Page对象
     *
     * @param resultList    page结果
     * @param navigatePages 页码数量
     */
    public PageInfo(Object resultList, int navigatePages) {
        calPageInfo(resultList, navigatePages);
    }

    private void calPageInfo(Object resultList, int navigatePages) {
        //pagehelper的分页
        if (resultList instanceof com.github.pagehelper.Page)
        {
            com.github.pagehelper.Page page = (com.github.pagehelper.Page) resultList;
            this.pageNo = page.getPageNum();
            this.pageSize = page.getPageSize();

            this.totalNum = page.getTotal();
            this.pageNum = page.getPages();
            this.list = page;
            this.currentPageSize = page.size();
            // 由于结果是>startRow的，所以实际的需要+1
            this.startRow = page.getStartRow() + 1;
            //jpa的分页
        } else if (resultList instanceof org.springframework.data.domain.Page) {
            org.springframework.data.domain.Page page = (org.springframework.data.domain.Page) resultList;
            this.pageNo = page.getNumber() + 1;
            this.pageSize = page.getPageable().getPageSize();

            this.totalNum = page.getTotalElements();
            this.pageNum = page.getTotalPages();
            this.list = page.getContent();
            this.currentPageSize = page.getNumberOfElements();
            // 由于结果是>startRow的，所以实际的需要+1
            this.startRow = (int) (page.getPageable().getOffset() + 1);
        }else{
            throw new BusinessException("不是分页结果集，无法计算");
        }
        // 计算实际的endRow（最后一页的时候特殊）
        this.endRow = this.startRow - 1 + this.currentPageSize;
        this.navigatePages = navigatePages;
        // 计算导航页
        calcNavigatepageNums();
        // 计算前后页，第一页，最后一页
        calcPage();
        // 判断页面边界
        judgePageBoudary();
//        }
    }

    public void setResultList(Object resultList) {
        calPageInfo(resultList, 8);
    }

    public void setResultList(Object resultList, int navigatePages) {
        calPageInfo(resultList, navigatePages);
    }

    /**
     * 计算导航页
     */
    private void calcNavigatepageNums() {
        // 当总页数小于或等于导航页码数时
        if (pageNum <= navigatePages) {
            navigatepageNums = new int[pageNum];
            for (int i = 0; i < pageNum; i++) {
                navigatepageNums[i] = i + 1;
            }
        } else { // 当总页数大于导航页码数时
            navigatepageNums = new int[navigatePages];
            int startNum = pageNo - navigatePages / 2;
            int endNum = pageNo + navigatePages / 2;

            if (startNum < 1) {
                startNum = 1;
                // (最前navigatePages页
                for (int i = 0; i < navigatePages; i++) {
                    navigatepageNums[i] = startNum++;
                }
            } else if (endNum > pageNum) {
                endNum = pageNum;
                // 最后navigatePages页
                for (int i = navigatePages - 1; i >= 0; i--) {
                    navigatepageNums[i] = endNum--;
                }
            } else {
                // 所有中间页
                for (int i = 0; i < navigatePages; i++) {
                    navigatepageNums[i] = startNum++;
                }
            }
        }
    }

    /**
     * 计算前后页，第一页，最后一页
     */
    private void calcPage() {
        if (navigatepageNums != null && navigatepageNums.length > 0) {
            firstPage = navigatepageNums[0];
            lastPage = navigatepageNums[navigatepageNums.length - 1];
            if (pageNo > 1) {
                prePage = pageNo - 1;
            }
            if (pageNo < pageNum) {
                nextPage = pageNo + 1;
            }
        }
    }

    /**
     * 判定页面边界
     */
    private void judgePageBoudary() {
        isFirstPage = pageNo == 1;
        isLastPage = pageNo == pageNum && pageNo != 1;
        hasPreviousPage = pageNo > 1;
        hasNextPage = pageNo < pageNum;
    }

    // public void setPageNum(int pageNum) {
    // this.pageNum = pageNum;
    // }
    //
    // public int getPageNum() {
    // return pageNum;
    // }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getStartRow() {
        return startRow;
    }

    // public long getTotal() {
    // return total;
    // }

    // public int getPages() {
    // return pages;
    // }

    public int getEndRow() {
        return endRow;
    }

    public List<T> getList() {
        return list;
    }

    public int getFirstPage() {
        return firstPage;
    }

    public int getPrePage() {
        return prePage;
    }

    public int getNextPage() {
        return nextPage;
    }

    public int getLastPage() {
        return lastPage;
    }

    public boolean isFirstPage() {
        return isFirstPage;
    }

    public boolean isLastPage() {
        return isLastPage;
    }

    public boolean isHasPreviousPage() {
        return hasPreviousPage;
    }

    public boolean isHasNextPage() {
        return hasNextPage;
    }

    public int getNavigatePages() {
        return navigatePages;
    }

    public int[] getNavigatepageNums() {
        return navigatepageNums;
    }

    public long getTotalNum() {
        return totalNum;
    }

    public int getPageNo() {
        return pageNo;
    }

    public void setPageNo(int pageNo) {
        this.pageNo = pageNo;
    }

    public int getPageNum() {
        return pageNum;
    }

    @Override
    public String toString() {
        return "PageInfo [pageNo=" + pageNo + ", pageSize=" + pageSize + ", currentPageSize=" + currentPageSize + ", startRow=" + startRow + ", endRow=" + endRow + ", totalNum=" + totalNum + ", pageNum=" + pageNum + ", firstPage=" + firstPage + ", prePage=" + prePage
                + ", nextPage=" + nextPage + ", lastPage=" + lastPage + ", isFirstPage=" + isFirstPage + ", isLastPage=" + isLastPage + ", hasPreviousPage=" + hasPreviousPage + ", hasNextPage=" + hasNextPage + ", navigatePages=" + navigatePages + ", navigatepageNums="
                + Arrays.toString(navigatepageNums) + "]";
    }
}
